Skip to content

[feat](inverted-index) Add IK tokenizers to custom analyzers - #67918

Open
airborne12 wants to merge 53 commits into
apache:masterfrom
airborne12:feature/ik-custom-tokenizers
Open

airborne12 wants to merge 53 commits into
apache:masterfrom
airborne12:feature/ik-custom-tokenizers

Conversation

@airborne12

@airborne12 airborne12 commented Sep 13, 2026 •

Copy link
Copy Markdown
Member

What problem does this PR solve?

Custom inverted-index analyzers could not use IK smart or max-word tokenization with their configured character and token filters. This adds the ik_smart and ik_max_word tokenizer factories and policy validation.

Composed pipelines need source-byte provenance across normalization, splitting, concatenation, trimming, and reset/reuse. Opt-in offset tracking propagates through IK, keyword, standard, ICU normalization, word-delimiter, and pinyin processing. Separate rune end offsets preserve gaps removed by delimiter concatenation.

Review fixes preserve exact saved policy bindings across replay, lifecycle operations, MATCH serialization, provider dispatch, physical reader selection, and scoring-statistics collection. FE matches explicit built-in IK to its default max-word configuration. BE selection keys distinguish mode, lowercase configuration, and effective outer character filters without changing provider names, Thrift, or stored index formats. Encoded configurations cannot collide with arbitrary policy names.

For backend-first upgrades, BE now binds an old FE's normalized analyzer name to the canonical saved policy and accepts a lowercase metadata key only when it resolves to the same policy. Exact metadata remains preferred. The compatibility alias cannot select a differently bound policy or a built-in analyzer with different tokenization.

Named character-filter identities account for transformations absorbed by the resolved tokenizer while preserving meaningful ordered transformations. The two new global-policy suites run in nonConcurrent instead of contributing to concurrent P0 policy-quota exhaustion.

Classic writer and query boundaries now convert lazy custom-analyzer failures to non-OK Status results. This includes ARRAY token-stream creation before add_document(), which clears the partial document and closes the writer on error instead of allowing a Doris exception to escape. FE identity construction also preserves case-folding absorption through the default icu_normalizer nfkc_cf filter, preventing equivalent lower-then-fold and fold-only pipelines from receiving different identities.

FE policy validation now checks an exact replayed policy before falling back to a normalized built-in analyzer or normalizer. This prevents a legacy wrong-type IK or LOWERCASE policy from passing FE validation and failing later in BE. CREATE ... IF NOT EXISTS also returns for an existing replayed ik_smart or ik_max_word policy before applying the reserved built-in-name check, while fresh creations with those names remain rejected.

Nested tokenizer, token-filter, and character-filter validation uses the same exact-first policy lookup as BE and enforces the expected component type. Replayed case-colliding policies can no longer bind a different saved component or the wrong filter family. When ICU token normalization changes text, its output carries a conservative source map to the original token span; unchanged tokens continue to delegate their precise upstream maps, and reset/reuse clears rewritten-map state.

The latest AI-review fixes reject duplicate non-IK analyzer selectors before full identity comparison, including the implicit default selector, so outer character-filter differences cannot create two indexes that the query syntax cannot distinguish. Basic, CharGroup, Empty, ICU, and NGram tokenizers now publish document-relative source boundaries for offset-aware Pinyin. ICU resolves monotonically increasing UTF-16 break boundaries with a constant-size UTF-8/UTF-16 cursor, transformations that change rune counts use a conservative whole-source span, and NGram byte offsets preserve full UChar32 values.

The memory fixes remove full-input dense offset tables from ICU tokenization and normalization. The tokenizer preserves exact spans with its incremental cursor. The normalizer retains opt-in provenance, stores no provenance when unused, and represents a changed token with one compact conservative source span when enabled; Pinyin consumes that span without forcing dense maps.

The current review fixes prevent rune-expanding ASCII folding and lowercase filters from forwarding invalid exact provenance, avoid allocating Pinyin rune and source arrays in the default ignore-offset mode, canonicalize FE analyzer identities using effective component defaults, and convert lazy scoring-analyzer failures back into Status results.

The final CI follow-up aligns the duplicate-analyzer unit test with the intentional selector-based diagnostic introduced by those validation fixes.

Current candidate: 31450230c09d6ba10b6f0c2e8de70f3765948543.

Release note

Add IK smart and max-word tokenizers to custom inverted-index analyzers. Correct composed-tokenizer source offsets, preserve custom-analyzer MATCH bindings during backend-first upgrades, select the matching physical IK configuration, and fix effective duplicate-index identities.

Check List (For Author)

  • Test:
    • Native FE and BE ASAN builds passed in the isolated task worktree. The BE build included the GLIBC 2.17 compatibility gate and its CDC client stage.
    • The official BE ASAN runner passed all 9 focused writer, reader, and analyzer failure-path tests, including the ARRAY pre-add_document() exception boundary. The complete InvertedIndexWriterTest suite passed 20/20.
    • The official FE runner passed all 22 AnalyzerIdentityBuilderTest tests. After policy-validation repairs, it also passed the replay/image coverage and all 40 PolicyValidatorTests; ./build.sh --fe completed successfully with zero Checkstyle violations.
    • The official BE ASAN runner passed 77/77 tests across IndexPolicyMgrTest, PinyinFilterTest, and ICUNormalizerFilterFactoryTest, including component type collisions and ICU-normalizer-to-pinyin source spans before and after reset.
    • A broader official BE ASAN run passed 354 tests in 10 related suites. A later tokenizer/filter run passed 150/150, and the two new offset-focused Pinyin tests passed 2/2 on the final source content.
    • The memory-fix candidate passed 203/203 related ASAN tokenizer and filter tests, including deterministic large-input allocation coverage for the ICU tokenizer and both disabled and enabled ICU-normalizer provenance paths. The full ASAN BE build then passed.
    • An official FE run passed 118 tests in four classes, including real index selection and MATCH-to-Thrift translation. The selector-ambiguity coverage passed 58/58 in InvertedIndexPropertiesTest.
    • The current review-fix candidate passed 147/147 related ASAN BE tests covering Pinyin, ASCII folding, lowercase, and scoring collection. A full ASAN BE build passed after the C++ changes.
    • The latest review-fix head passed 112/112 targeted BE ASAN tests across ICU, Keyword, NGram, and Pinyin coverage. It also passed 86/86 FE tests across AnalyzerIdentityBuilderTest and InvertedIndexPropertiesTest; the full 80-module Maven reactor and Checkstyle completed successfully.
    • The final candidate passed all 22 SchemaChangeHandlerTest tests and the complete 80-module Maven reactor after updating its stale duplicate-analyzer diagnostic expectation.
    • Discriminating native RED/GREEN tests cover legacy exact reader metadata, normalized index metadata, policy-name collisions, a reserved built-in-name collision, canonical-key precedence, legacy normalizers, scoring selection, encoded-policy-name collisions, ambiguous non-IK selectors, document-relative Pinyin offsets for every custom tokenizer, retained allocations for large ICU inputs, rune-expansion provenance, default Pinyin allocation behavior, explicit component defaults, and scoring analyzer failures.
    • test_ik_custom_analyzer, test_analyzer_identity_semantics, and existing test_ik_analyzer passed earlier against the task-owned native ASAN cluster. The targeted analyzer-identity regression passed 1/1; the Basic CREATE/ALTER cases added by the latest review fix were not run locally.
    • The current candidate contains 26 PR commits relative to merge base bf127c2d9ca1cdbb70c604320120fea1f1e33002; exact merge-tree preflight against target snapshot 3750a819a2af157ad539d947bc301ff0f806b928 passed before publication.
    • The full committed PR English audit passed for 78 source files. Thirty-seven precisely reviewed Unicode input and expected-token literals remain as test data; no descriptive text was exempted.
    • Clang-tidy 16 reported no changed-line warnings in the modified production sources. Three ASAN test translation units could not be analyzed because the local clang-tidy resource headers lack the sanitizer headers; no suppression was added.
    • Exact-current-head merged-snapshot clang-format 16 and all FE reactor Checkstyle modules passed in the shared publication gate before push.
    • Local results are not a claim that fresh full CI or AI review passed. Those runs are requested and evaluated against the published candidate.
  • Behavior changed: Yes. Custom analyzers support IK tokenization; saved policy bindings, physical index selection, source offsets, effective duplicate-index identities, and analyzer selection remain consistent across query and DDL paths.
  • Does this need documentation: No new syntax is introduced. Existing analyzer configuration syntax is reused; no documentation changes are included.

Component-level replay, serialization, dispatch, reader selection, scoring selection, and current-version end-to-end regression were validated. A full mixed-version cluster upgrade was not run. Existing IK internal lowercasing behavior is unchanged; the uppercase SQL probe is not treated as proof of a lowercase-disabled runtime fix.

@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@airborne12

Copy link
Copy Markdown
Member Author

run buildall

@airborne12

Copy link
Copy Markdown
Member Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review of exact head 1ecadcaebb31e4bdfc8139194e9434eb044cdea1. Requesting changes for 1 P0, 6 P1, and 1 P2 findings.

Critical checkpoint conclusions

  • Goal and proof: The goal is to expose ik_smart and ik_max_word as custom-analyzer tokenizers. The lowercase scalar happy path is wired, but the P0 reset regression and the policy, offset, and phrase failures mean the implementation does not yet satisfy the supported public paths. The added tests prove selected terms only.
  • Scope/focus: The production change is small and focused, but its integration surface is broader than the tests cover. No user-specific focus was provided, so the complete PR was reviewed.
  • Concurrency: Factory and dictionary publication use call_once; all production IK initializers use the same dictionary path, per-tokenizer mode remains local, and loaded tries are read-only. No new race, lock-order, deadlock, or heavy-under-lock issue was found.
  • Lifecycle/static initialization: Dictionary initialization is safe, but tokenizer reset lifecycle is not: CLucene's mandatory reset-before-consume crashes legacy IK indexing and destructively empties custom ARRAY token streams. Reader ownership and retained token storage are otherwise sound on the traced paths.
  • Configuration: No new Doris runtime configuration item is added. Existing dictionary configuration remains restart-only and is used consistently.
  • Compatibility: No wire/storage-format symbol is added, and the documented BE-then-FE rolling sequence covers factory availability. However, previously legal persisted policies named ik_smart/ik_max_word now collide, with FE and BE choosing different meanings.
  • Parallel paths: Scalar custom reuse works, but legacy and ARRAY CLucene paths fail reset; both legacy CLucene and SNII phrase readers mishandle same-position pinyin alternatives, while the query-v2 CLucene path groups them.
  • Conditional logic: No additional unsupported special condition was found. The missing FE validator cases and inconsistent normalization are called out inline.
  • Test coverage: Missing cases include legacy IndexWriter, custom ARRAY, named TOKENIZER policies, mixed-case/noncanonical references, replay collisions, exact offsets, multibyte refill boundaries, and MATCH_PHRASE across storage implementations.
  • Test results: BE/FE tests and a regression suite were added, but their assertions do not cover the failing paths; the regression also violates required golden-output/table-name conventions. Per the review contract, I did not run builds or tests, so all conclusions are static and author/CI claims are not independent execution evidence.
  • Observability: No new metrics or logging are required for this registry exposure; existing exception boundaries are adequate once the correctness defects are fixed. The ARRAY failure is silent data omission and must be corrected rather than observed around.
  • Persistence/transactions: No transaction state machine changes. Existing policy journaling/replay is structurally used, but replayed-name collision semantics are incompatible as noted inline.
  • Data writes: Index construction is materially affected: existing legacy IK writes can crash and custom IK ARRAY values can contribute no terms. No separate rowset/version/MoW issue was introduced.
  • FE-BE variables: No new Thrift field is needed, but existing string-valued policy transport preserves a spelling that FE accepts and BE's exact factory lookup rejects.
  • Performance: No new asymptotic hot-path or material memory-accounting issue was substantiated; repeated dictionary initialization is only a completed call_once check.
  • Other issues: After two full rounds, including separate lifecycle/phrase and dictionary/policy risk passes, all reviewers returned NO_NEW_VALUABLE_FINDINGS. One char-filter candidate was disproven by concrete overrides and is intentionally not submitted.

Please address the eight inline findings before merge.

Comment thread be/src/storage/index/inverted/analyzer/ik/IKTokenizer.cpp Outdated
Comment thread be/src/storage/index/inverted/analyzer/ik/IKTokenizer.cpp
Comment thread be/src/storage/index/inverted/analyzer/ik/IKTokenizer.cpp Outdated
Comment thread regression-test/suites/inverted_index_p0/analyzer/test_ik_custom_analyzer.groovy Outdated
Comment thread regression-test/suites/inverted_index_p0/analyzer/test_ik_custom_analyzer.groovy Outdated
@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 16654 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 1ecadcaebb31e4bdfc8139194e9434eb044cdea1, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17563	3080	3069	3069
q2	2065	249	208	208
q3	10284	883	506	506
q4	4666	248	197	197
q5	7693	568	388	388
q6	135	110	90	90
q7	525	498	389	389
q8	9227	848	923	848
q9	3441	2363	2361	2361
q10	6494	858	712	712
q11	404	197	179	179
q12	622	263	195	195
q13	18120	1540	1168	1168
q14	159	151	138	138
q15	q16	430	390	372	372
q17	1381	862	815	815
q18	3084	2245	2205	2205
q19	1266	866	743	743
q20	369	286	194	194
q21	5650	1641	1825	1641
q22	328	271	236	236
Total cold run time: 93906 ms
Total hot run time: 16654 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3436	3403	3368	3368
q2	506	390	390	390
q3	2206	2267	2175	2175
q4	1187	1160	881	881
q5	2178	2097	2101	2097
q6	167	117	88	88
q7	1024	891	838	838
q8	1591	1413	1413	1413
q9	3108	3093	3076	3076
q10	1857	1801	1617	1617
q11	357	269	252	252
q12	450	427	341	341
q13	1492	1508	1123	1123
q14	177	166	162	162
q15	q16	394	399	352	352
q17	3548	3289	3168	3168
q18	4765	4363	4748	4363
q19	855	783	898	783
q20	1070	966	832	832
q21	3842	3117	3288	3117
q22	414	358	329	329
Total cold run time: 34624 ms
Total hot run time: 30765 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 81543 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 1ecadcaebb31e4bdfc8139194e9434eb044cdea1, data reload: false

query5	4226	416	341	341
query6	380	133	128	128
query7	4960	428	236	236
query8	284	117	114	114
query9	8688	2832	2858	2832
query10	416	228	185	185
query11	5376	1036	916	916
query12	121	70	70	70
query13	1190	452	322	322
query14	6087	2203	2069	2069
query14_1	1981	1954	1952	1952
query15	175	119	114	114
query16	921	366	332	332
query17	803	479	371	371
query18	2321	350	244	244
query19	163	140	115	115
query20	73	72	72	72
query21	207	103	89	89
query22	5339	5305	5359	5305
query23	6774	6243	5948	5948
query23_1	6049	6070	6005	6005
query24	7343	1103	743	743
query24_1	769	769	798	769
query25	425	303	257	257
query26	1243	242	133	133
query27	2769	399	257	257
query28	4707	1475	1491	1475
query29	926	429	359	359
query30	264	156	132	132
query31	830	425	331	331
query32	131	78	80	78
query33	462	227	182	182
query34	1002	840	496	496
query35	406	402	348	348
query36	565	571	525	525
query37	127	86	72	72
query38	1013	850	792	792
query39	496	490	474	474
query39_1	490	452	473	452
query40	201	100	80	80
query41	58	57	58	57
query42	75	75	72	72
query43	244	242	210	210
query44	1007	539	541	539
query45	118	111	100	100
query46	764	860	508	508
query47	768	786	722	722
query48	325	319	238	238
query49	585	253	199	199
query50	775	256	192	192
query51	7998	7966	7989	7966
query52	67	68	60	60
query53	191	196	151	151
query54	218	182	148	148
query55	79	60	54	54
query56	189	160	167	160
query57	687	720	664	664
query58	193	192	170	170
query59	1209	1209	1099	1099
query60	238	195	178	178
query61	118	117	132	117
query62	361	220	184	184
query63	174	138	139	138
query64	2698	678	628	628
query65	1635	1583	1576	1576
query66	1870	278	225	225
query67	9742	9379	9684	9379
query68	2930	1189	768	768
query69	343	231	194	194
query70	672	623	617	617
query71	262	168	158	158
query72	2280	1750	1499	1499
query73	652	636	351	351
query74	1987	1233	1138	1138
query75	1189	1125	982	982
query76	2345	700	513	513
query77	258	274	202	202
query78	3867	3686	3239	3239
query79	2299	841	614	614
query80	1635	330	283	283
query81	485	157	132	132
query82	631	126	103	103
query83	274	212	191	191
query84	301	109	87	87
query85	783	342	281	281
query86	386	181	173	173
query87	1011	970	893	893
query88	2800	2112	2116	2112
query89	280	198	177	177
query90	1982	136	138	136
query91	128	119	97	97
query92	74	74	72	72
query93	1384	1142	717	717
query94	645	239	235	235
query95	539	245	291	245
query96	839	616	285	285
query97	1054	1039	992	992
query98	142	138	138	138
query99	419	354	319	319
Total cold run time: 177364 ms
Total hot run time: 81543 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 14.57 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 1ecadcaebb31e4bdfc8139194e9434eb044cdea1, data reload: false

query1	0.00	0.00	0.01
query2	0.08	0.04	0.03
query3	0.26	0.11	0.10
query4	1.59	0.09	0.10
query5	0.17	0.16	0.15
query6	1.29	0.70	0.67
query7	0.03	0.01	0.00
query8	0.04	0.03	0.03
query9	0.29	0.21	0.21
query10	0.33	0.35	0.34
query11	0.16	0.13	0.13
query12	0.14	0.13	0.12
query13	0.30	0.29	0.30
query14	0.43	0.45	0.44
query15	0.35	0.35	0.35
query16	0.23	0.23	0.22
query17	0.67	0.68	0.67
query18	0.16	0.15	0.15
query19	1.13	1.18	1.17
query20	0.02	0.01	0.01
query21	15.44	0.15	0.12
query22	5.08	0.04	0.04
query23	16.19	0.26	0.10
query24	3.06	0.33	0.26
query25	0.12	0.04	0.04
query26	0.77	0.17	0.12
query27	0.03	0.03	0.03
query28	3.65	0.58	0.29
query29	12.41	3.17	2.57
query30	0.28	0.11	0.14
query31	2.77	0.38	0.17
query32	3.49	0.31	0.24
query33	1.36	1.54	1.37
query34	15.34	2.20	1.76
query35	1.74	1.67	1.72
query36	0.46	0.29	0.29
query37	0.07	0.04	0.03
query38	0.05	0.03	0.03
query39	0.03	0.02	0.03
query40	0.12	0.08	0.07
query41	0.08	0.02	0.03
query42	0.03	0.03	0.02
query43	0.03	0.03	0.03
Total cold run time: 90.27 s
Total hot run time: 14.57 s

airborne12 added a commit to airborne12/apache-doris that referenced this pull request Sep 13, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#67918

Problem Summary:

The initial IK custom-analyzer integration did not fully preserve tokenizer reset semantics, document-relative UTF-8 offsets, case-insensitive built-in resolution, or upgrade compatibility when an existing named policy collides with a new built-in name. Its regression coverage also lacked generated golden output.

Preserve the pending-reader reset contract, advance refill offsets by consumed bytes, rebase pinyin candidates to source-token byte spans, canonicalize built-in names while keeping named policies authoritative, accept IK tokenizer policy types in FE validation, and add focused unit and regression coverage.

### Release note

None

### Check List (For Author)

- Test
    - [x] Regression test
    - [x] Unit Test
    - [x] Manual test
- Behavior changed:
    - [x] No. This corrects edge cases in the feature introduced by the preceding commit.
    - [ ] Yes.
- Does this need documentation?
    - [x] No.
    - [ ] Yes.

Validation:

- `./build.sh --be -j48` (ASAN)
- `./build.sh --fe`
- `./run-be-ut.sh --run --filter='IKTokenizerTest.*' -j48` (21 tests passed)
- `./run-be-ut.sh --run --filter='AnalysisFactoryMgrTest.*:IKTokenizerTest.*:PinyinFilterTest.*:IndexPolicyMgrTest.*' -j48` (80 passed; one pre-existing order-dependent dictionary-initialization test failed, then passed in the isolated IK run)
- `./run-fe-ut.sh --run --filter=org.apache.doris.analysis.invertedindex.AnalyzerIdentityBuilderTest` (6 tests passed)
- `./run-fe-ut.sh --run --filter=org.apache.doris.indexpolicy.PolicyValidatorTests` (20 tests passed)
- `./run-regression-test.sh --run -s test_ik_custom_analyzer -d inverted_index_p0/analyzer` (generated golden and clean comparison passed)
- clang-tidy on all changed C++ lines with the ASAN compilation database; one test translation unit is blocked by the pre-existing unmatched `NOLINTEND` in `be/src/core/types.h`
- C++ format, Checkstyle, build-hygiene, and glibc compatibility checks

The Chinese literals in the tests and regression golden are tokenizer input and expected token data, not code descriptions.
@airborne12

Copy link
Copy Markdown
Member Author

run buildall

@airborne12

Copy link
Copy Markdown
Member Author

/review

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 16855 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 33dd82008708152608064761581e49b9d1475744, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17603	3081	3059	3059
q2	2066	253	218	218
q3	10258	871	528	528
q4	4669	255	212	212
q5	7654	561	385	385
q6	137	114	96	96
q7	539	512	390	390
q8	9255	897	912	897
q9	3446	2421	2398	2398
q10	6508	862	710	710
q11	418	198	186	186
q12	627	269	203	203
q13	18092	1521	1156	1156
q14	166	149	139	139
q15	q16	440	403	374	374
q17	1365	878	752	752
q18	3106	2285	2263	2263
q19	1286	944	734	734
q20	394	291	201	201
q21	5698	1720	1896	1720
q22	340	272	234	234
Total cold run time: 94067 ms
Total hot run time: 16855 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3459	3396	3355	3355
q2	509	394	375	375
q3	2211	2353	2203	2203
q4	1204	1167	898	898
q5	2193	2148	2091	2091
q6	170	120	89	89
q7	1046	910	855	855
q8	1586	1400	1399	1399
q9	3160	3132	3109	3109
q10	1852	1804	1622	1622
q11	354	270	248	248
q12	457	434	355	355
q13	1507	1545	1137	1137
q14	167	176	161	161
q15	q16	399	399	360	360
q17	3542	3346	3194	3194
q18	4823	4422	4735	4422
q19	841	915	866	866
q20	1003	967	832	832
q21	3854	3226	3164	3164
q22	400	344	317	317
Total cold run time: 34737 ms
Total hot run time: 31052 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 82284 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 33dd82008708152608064761581e49b9d1475744, data reload: false

query5	4274	419	358	358
query6	388	166	132	132
query7	4889	434	227	227
query8	302	127	128	127
query9	8718	2934	2950	2934
query10	399	235	213	213
query11	5401	1052	927	927
query12	137	75	71	71
query13	1192	453	327	327
query14	6192	2210	2106	2106
query14_1	1999	1976	1962	1962
query15	181	121	114	114
query16	973	374	378	374
query17	810	457	386	386
query18	2325	312	225	225
query19	155	135	107	107
query20	83	70	71	70
query21	198	99	86	86
query22	5466	5455	5330	5330
query23	6863	6351	5994	5994
query23_1	6127	6005	6068	6005
query24	7237	1074	772	772
query24_1	750	782	778	778
query25	408	279	233	233
query26	1223	224	128	128
query27	2810	423	259	259
query28	4666	1513	1500	1500
query29	929	422	340	340
query30	252	160	131	131
query31	822	402	325	325
query32	125	74	78	74
query33	451	229	172	172
query34	1000	822	474	474
query35	398	395	336	336
query36	572	567	531	531
query37	118	78	70	70
query38	1023	854	824	824
query39	493	498	473	473
query39_1	502	456	445	445
query40	206	88	77	77
query41	53	51	51	51
query42	72	70	72	70
query43	246	239	208	208
query44	1032	539	530	530
query45	108	104	103	103
query46	765	828	539	539
query47	762	769	729	729
query48	304	309	232	232
query49	549	243	189	189
query50	736	265	188	188
query51	8131	8221	8168	8168
query52	67	68	60	60
query53	199	192	148	148
query54	219	154	150	150
query55	71	61	56	56
query56	274	168	168	168
query57	683	678	625	625
query58	203	167	162	162
query59	1205	1247	1113	1113
query60	230	198	185	185
query61	144	108	125	108
query62	349	201	180	180
query63	172	140	141	140
query64	2665	719	660	660
query65	1700	1610	1643	1610
query66	1840	274	212	212
query67	9892	9795	9925	9795
query68	3007	1176	686	686
query69	350	228	199	199
query70	687	636	626	626
query71	259	183	169	169
query72	2340	1683	1480	1480
query73	667	576	328	328
query74	1995	1243	1126	1126
query75	1180	1106	959	959
query76	2376	718	510	510
query77	251	268	214	214
query78	4073	3701	3159	3159
query79	2446	809	546	546
query80	1612	325	266	266
query81	517	159	132	132
query82	646	126	94	94
query83	303	217	190	190
query84	293	108	86	86
query85	834	348	288	288
query86	393	174	169	169
query87	1023	975	893	893
query88	2775	2144	2143	2143
query89	299	197	176	176
query90	1966	135	131	131
query91	133	124	99	99
query92	80	70	71	70
query93	1554	1091	733	733
query94	647	249	231	231
query95	542	263	232	232
query96	759	573	273	273
query97	1043	1091	1068	1068
query98	140	143	133	133
query99	441	348	312	312
Total cold run time: 178783 ms
Total hot run time: 82284 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 14.94 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 33dd82008708152608064761581e49b9d1475744, data reload: false

query1	0.00	0.01	0.00
query2	0.07	0.04	0.04
query3	0.25	0.11	0.10
query4	1.60	0.09	0.10
query5	0.17	0.16	0.16
query6	1.28	0.70	0.71
query7	0.03	0.01	0.00
query8	0.04	0.03	0.03
query9	0.28	0.22	0.21
query10	0.34	0.36	0.36
query11	0.16	0.12	0.12
query12	0.15	0.12	0.13
query13	0.31	0.31	0.32
query14	0.44	0.44	0.45
query15	0.36	0.35	0.36
query16	0.23	0.22	0.22
query17	0.69	0.75	0.70
query18	0.18	0.17	0.17
query19	1.15	1.17	1.13
query20	0.02	0.01	0.01
query21	15.46	0.16	0.11
query22	5.07	0.04	0.04
query23	16.18	0.26	0.10
query24	2.99	0.34	0.28
query25	0.11	0.03	0.03
query26	0.84	0.16	0.13
query27	0.03	0.03	0.03
query28	3.67	0.53	0.28
query29	12.49	3.19	2.59
query30	0.26	0.11	0.12
query31	2.77	0.37	0.18
query32	3.53	0.32	0.23
query33	1.54	1.50	1.51
query34	15.37	2.21	1.82
query35	1.78	1.75	1.73
query36	0.45	0.29	0.29
query37	0.06	0.04	0.04
query38	0.04	0.03	0.03
query39	0.03	0.02	0.02
query40	0.12	0.08	0.07
query41	0.08	0.02	0.03
query42	0.03	0.02	0.02
query43	0.04	0.03	0.03
Total cold run time: 90.69 s
Total hot run time: 14.94 s

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes — static review completed and converged at exact head 33dd82008708152608064761581e49b9d1475744 against base 2573820600eb178150a35710a94fd58b478df96d.

Five distinct P1 findings are attached inline: aggregate BE test-order dependence, locale-dependent IK name normalization, loss of source-byte boundaries after fullwidth normalization, non-canonical built-in filter identities, and unequal identities for direct versus type-only named IK tokenizers.

Critical checkpoint conclusions:

  • Goal and proof: the patch registers both IK modes and adds FE, BE, and regression coverage, but the goal is not safely complete while the combined BE test binary is order-dependent and the offset/identity cases above remain uncovered.
  • Scope: the production change is focused on analyzer registration, reset/offset propagation, policy validation, and identity. All 19 changed files and their upstream/downstream paths were reviewed; no additional user focus was provided.
  • Concurrency: factory registration and dictionary initialization use process-wide call_once; FE policy maps remain lock-protected. No runtime race, lock-order, or deadlock issue was found. The singleton lifecycle does create the accepted cross-test failure.
  • Lifecycle: fresh/reusable custom streams, legacy raw-reader streams, scalar/ARRAY indexing, reader ownership, and repeated reset were traced; the current reset fix preserves ownership and tokenizes once per reader. Global dictionary test state is not isolated.
  • Configuration: no new dynamic or persisted configuration key is introduced; both factories consume the existing dictionary path and keep smart/max-word mode per stream. No runtime configuration propagation gap was found.
  • Compatibility: existing named-policy precedence is aligned across FE replay/identity and BE resolution, and unsupported mixed-version direct use fails explicitly rather than silently reinterpreting metadata. Locale normalization and semantic identity consistency still need the inline fixes.
  • Parallel paths and conditions: tokenizer, token-filter, and char-filter resolution plus both CREATE TABLE and CREATE INDEX identity consumers were checked. The filter and named-wrapper branches are the missing parallel cases reported inline.
  • Tests and results: regression ordering/goldens are structurally deterministic, but negative Unicode/locale/identity coverage is missing. Per review-runner contract I ran no builds or tests. Author-reported validation includes a combined relevant BE run failure followed by an isolated IK pass; live CI currently has formatter, Checkstyle, license, secrets, Cloud UT, and performance passing while BE UT, FE UT, and compile remain pending.
  • Observability: existing exception and logging paths are adequate for this local analyzer feature; no new metric is warranted.
  • Persistence and transactions: policy image/replay, name-map rebuilding, propagation, and drop/reference paths were traced. No EditLog payload, transaction protocol, or storage-format change is introduced.
  • Data writes and crash behavior: index-writer scalar/ARRAY paths were checked; no new transactional atomicity or crash-leak issue was found beyond incorrect offsets and duplicate-index admission.
  • FE/BE variables: no new thrift field or scattered session variable is introduced; existing policy properties carry the component names.
  • Performance and memory: eager IK buffering is pre-existing; retaining two offsets per token adds bounded metadata and no new hot-loop or tracked-allocation regression was substantiated.
  • Other correctness: error propagation and position increments are consistent. All prior threads were treated as hard duplicate fences, every candidate was resolved, and the third round returned NO_NEW_VALUABLE_FINDINGS from all reviewers.

Comment thread be/test/runtime/index_policy/index_policy_mgr_test.cpp Outdated
Comment thread be/src/storage/index/inverted/token_filter/pinyin_filter.cpp
airborne12 added a commit to airborne12/apache-doris that referenced this pull request Sep 13, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#67918

Problem Summary:

The IK analyzer integration could initialize global dictionaries from a factory-resolution test, depend on the JVM default locale, produce distinct identities for equivalent built-in components, and lose original byte boundaries when IK regularization changes UTF-8 width.

Keep the factory-resolution test side-effect free, normalize names with Locale.ROOT, canonicalize all built-in component identities and type-only wrappers, and propagate source rune boundaries through token filters so pinyin offsets remain relative to the original document.

### Release note

None

### Check List (For Author)

- Test
    - [x] Regression test
    - [x] Unit Test
    - [x] Manual test
- Behavior changed:
    - [x] No. This corrects edge cases in the feature introduced by the preceding commits.
    - [ ] Yes.
- Does this need documentation?
    - [x] No.
    - [ ] Yes.

Validation:

- ./build.sh --be -j8 (ASAN)
- ./build.sh --fe -j8
- IKTokenizerTest and PinyinFilterTest (62 tests passed)
- AnalysisFactoryMgrTest, IKTokenizerTest, PinyinFilterTest, and IndexPolicyMgrTest (82 tests passed)
- AnalyzerIdentityBuilderTest and PolicyValidatorTests (29 tests passed)
- clang-format 16 and Checkstyle passed
- clang-tidy found no warnings on analyzable changed lines; one deletion-only test translation unit remains blocked by a pre-existing unmatched NOLINTEND in be/src/core/types.h

The fullwidth literal in the test is tokenizer input data, not a code description.
@airborne12

Copy link
Copy Markdown
Member Author

run buildall

@airborne12

Copy link
Copy Markdown
Member Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review complete at head c5976f7cff0c8aae1f3dc174a377d1446b70c315 after two convergence rounds. Requesting changes for one distinct P1 issue described inline.

Critical checkpoint conclusions:

  • Goal and test approach: The PR wires ik_smart and ik_max_word through FE policy validation, BE factory construction, TOKENIZE/query, index writing, and regression coverage. The implementation goal is coherent, but semantic duplicate detection is incomplete across the legacy and custom IK entry points.
  • Scope and focus: Reviewed all 22 authoritative changed paths and their confirmed callers/consumers. The user supplied no additional focus, so the full PR remained in scope.
  • Concurrency: FE policy-map locking, factory registration, and the process-wide IK dictionary initialization were traced; no distinct new runtime race or lock-order defect was found.
  • Lifecycle and static initialization: Legacy/custom raw and shared readers, reusable scalar streams, ARRAY streams, reset/error recovery, dictionary lifetime, and filter span lifetime were checked. Residual test-order concerns are already covered by an existing thread and were not duplicated.
  • Configuration: No new dynamic-config contract is introduced. Both IK modes use the established dictionary path; configuration normalization issues substantially covered by existing threads were fenced.
  • Compatibility and rolling upgrade: No new persisted or wire schema is added. Policy replay/publication and existing-policy-first name collisions were checked; normal BE-first rollout is required for the new factories, with no separate compatibility defect found.
  • Parallel and special-case paths: Checked smart, implicit-smart, and max-word modes; direct and named/type-only references; CREATE TABLE and ALTER/CREATE INDEX; scalar and ARRAY writes; TOKENIZE, MATCH, and query analysis. The cross-family duplicate gap affects both DDL paths.
  • Conditionals, comments, and similar implementations: Compared legacy IKAnalyzer construction with IKTokenizerFactory, reviewed normalization precedence and related tokenizer/filter factories, and traced source-offset/refill/truncation branches. No additional distinct issue survived the duplicate fences.
  • Tests: Changed BE unit, FE unit, and regression tests cover registration, validation, reset/reuse, refills, offsets, pinyin composition, both IK modes, TOKENIZE, and MATCH. Cross-family duplicate tests are missing and are requested with the inline finding. This reviewer ran no builds or tests because the review contract prohibited execution. The author reports ASAN builds, 82 combined BE tests, 29 FE tests, and the regression case; at submission time BE UT, FE UT, compile, performance, and review checks were still pending in CI.
  • Outputs: The regression golden is ordered/deterministic for the asserted queries and follows cleanup-before-use conventions. No distinct output-contract issue was found.
  • Observability and errors: Existing exceptions/status propagation and relevant logging remain in place; no new silent production failure or observability gap was found outside the identity bug.
  • Persistence and transactions: Index-policy journal/replay/image reconstruction and FE-to-BE publication were traced. No transaction-state, metadata-format, or replay-order defect was found.
  • Writes, atomicity, and crash behavior: Scalar/ARRAY index-writer consumption and reset ordering were reviewed; no new atomicity, partial-write, or crash-recovery issue was found.
  • FE/BE variables and all consumers: No Thrift field is added. FE names and BE factories align for valid direct/named policies, but FE's analyzer identity does not unify the equivalent legacy IK representation, which is the blocking finding.
  • Performance: Source-byte mapping is allocated only for width-changing normalization and the identity work remains DDL-side; no material new performance issue was substantiated.
  • Other: Security review was not requested or implicated. Existing inline issues and replies were treated as hard duplicate fences and were not reposted.

Review status: complete static review; one new blocking finding; exact base/head verified before submission.

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 85.00% (17/20) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 63.28% (29643/46844)
Line Coverage 48.19% (309651/642588)
Region Coverage 43.71% (249283/570269)
Branch Coverage 45.33% (116106/256159)

airborne12 added a commit to airborne12/apache-doris that referenced this pull request Sep 13, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#67918

Problem Summary:

Legacy IK parser indexes and equivalent custom analyzers used different semantic identities, allowing duplicate inverted indexes on one column. Canonicalize unfiltered legacy smart and max-word modes to the corresponding custom analyzer identities while preserving distinct identities for filtered legacy analyzers.

### Release note

None

### Check List (For Author)

- Test
    - [x] Regression test
    - [x] Unit Test

- Behavior changed:
    - [x] Yes. Equivalent legacy and custom IK indexes are now rejected as duplicates.

- Does this need documentation?
    - [x] No.
@airborne12

Copy link
Copy Markdown
Member Author

run buildall

@airborne12

Copy link
Copy Markdown
Member Author

/review

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 16675 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 0e66fd9522552abd9efa2bb685db6970859b19d1, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17561	2984	2958	2958
q2	2065	248	215	215
q3	10280	869	513	513
q4	4663	248	205	205
q5	7676	549	384	384
q6	139	115	93	93
q7	533	508	384	384
q8	9229	927	906	906
q9	3434	2402	2361	2361
q10	6517	857	702	702
q11	405	197	184	184
q12	616	257	197	197
q13	18127	1498	1141	1141
q14	177	150	137	137
q15	q16	436	390	369	369
q17	1326	875	814	814
q18	3043	2197	2234	2197
q19	1118	851	799	799
q20	379	281	205	205
q21	5229	1674	1853	1674
q22	325	265	237	237
Total cold run time: 93278 ms
Total hot run time: 16675 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3337	3278	3269	3269
q2	509	387	372	372
q3	2204	2258	2152	2152
q4	1177	1159	871	871
q5	2157	2073	2086	2073
q6	171	119	85	85
q7	1030	944	834	834
q8	1574	1367	1364	1364
q9	3067	3033	3018	3018
q10	1845	1789	1609	1609
q11	349	266	246	246
q12	446	421	343	343
q13	1467	1533	1141	1141
q14	172	162	154	154
q15	q16	389	392	360	360
q17	3531	3298	3247	3247
q18	4736	4397	4739	4397
q19	863	845	807	807
q20	992	1106	806	806
q21	3699	3047	3145	3047
q22	398	348	338	338
Total cold run time: 34113 ms
Total hot run time: 30533 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 81320 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 0e66fd9522552abd9efa2bb685db6970859b19d1, data reload: false

query5	4270	420	343	343
query6	388	140	126	126
query7	4935	427	229	229
query8	298	126	119	119
query9	8724	2876	2886	2876
query10	411	241	197	197
query11	5395	1052	910	910
query12	123	71	69	69
query13	1192	432	321	321
query14	6059	2216	2098	2098
query14_1	1986	1968	1966	1966
query15	173	121	117	117
query16	889	360	334	334
query17	764	419	331	331
query18	2312	313	227	227
query19	159	132	107	107
query20	74	70	67	67
query21	201	99	85	85
query22	5358	5466	5330	5330
query23	6578	6192	6003	6003
query23_1	6117	6124	5980	5980
query24	7268	1055	742	742
query24_1	758	775	773	773
query25	408	269	229	229
query26	1231	230	122	122
query27	2793	416	246	246
query28	4726	1477	1490	1477
query29	918	408	358	358
query30	250	152	126	126
query31	799	401	321	321
query32	121	68	70	68
query33	447	218	172	172
query34	986	827	480	480
query35	411	402	332	332
query36	565	577	511	511
query37	119	82	67	67
query38	987	851	792	792
query39	495	475	480	475
query39_1	458	449	456	449
query40	200	88	76	76
query41	55	54	52	52
query42	74	69	71	69
query43	237	236	207	207
query44	985	536	544	536
query45	111	107	105	105
query46	785	808	513	513
query47	788	784	709	709
query48	313	301	234	234
query49	541	243	205	205
query50	723	265	194	194
query51	8022	7957	7807	7807
query52	67	67	57	57
query53	192	199	149	149
query54	206	174	138	138
query55	68	58	53	53
query56	197	183	173	173
query57	675	667	658	658
query58	202	170	200	170
query59	1284	1242	1105	1105
query60	234	185	170	170
query61	114	124	127	124
query62	368	205	180	180
query63	167	137	140	137
query64	2753	755	695	695
query65	1619	1566	1650	1566
query66	1897	289	248	248
query67	9845	9525	9466	9466
query68	2740	1201	760	760
query69	337	228	213	213
query70	682	620	627	620
query71	248	176	174	174
query72	2325	1686	1445	1445
query73	643	619	349	349
query74	1553	1232	1140	1140
query75	1172	1100	960	960
query76	2278	699	503	503
query77	242	251	215	215
query78	4058	3645	3246	3246
query79	2849	810	555	555
query80	1605	328	272	272
query81	513	157	134	134
query82	616	140	97	97
query83	271	207	187	187
query84	288	113	89	89
query85	801	337	318	318
query86	472	174	168	168
query87	1003	963	890	890
query88	3026	2093	2098	2093
query89	274	195	173	173
query90	2136	118	133	118
query91	128	119	98	98
query92	88	70	71	70
query93	2245	1060	675	675
query94	644	248	205	205
query95	511	271	222	222
query96	800	608	276	276
query97	1027	1092	1010	1010
query98	177	130	133	130
query99	412	339	310	310
Total cold run time: 178476 ms
Total hot run time: 81320 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 14.6 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 0e66fd9522552abd9efa2bb685db6970859b19d1, data reload: false

query1	0.01	0.00	0.01
query2	0.08	0.03	0.04
query3	0.25	0.12	0.11
query4	1.60	0.11	0.09
query5	0.16	0.15	0.16
query6	1.27	0.70	0.69
query7	0.03	0.01	0.00
query8	0.07	0.04	0.03
query9	0.28	0.21	0.21
query10	0.35	0.34	0.35
query11	0.16	0.11	0.12
query12	0.14	0.12	0.11
query13	0.30	0.31	0.30
query14	0.45	0.44	0.44
query15	0.37	0.35	0.35
query16	0.20	0.23	0.22
query17	0.71	0.68	0.68
query18	0.18	0.17	0.17
query19	1.22	1.20	1.09
query20	0.02	0.01	0.01
query21	15.43	0.17	0.12
query22	5.08	0.05	0.04
query23	16.18	0.26	0.10
query24	3.01	0.33	0.24
query25	0.12	0.03	0.02
query26	0.78	0.16	0.13
query27	0.04	0.03	0.03
query28	3.64	0.56	0.27
query29	12.48	3.13	2.53
query30	0.26	0.11	0.12
query31	2.75	0.38	0.17
query32	3.52	0.32	0.22
query33	1.34	1.49	1.52
query34	15.32	2.16	1.78
query35	1.75	1.76	1.70
query36	0.45	0.30	0.29
query37	0.06	0.04	0.04
query38	0.04	0.04	0.03
query39	0.03	0.02	0.02
query40	0.11	0.07	0.08
query41	0.07	0.03	0.02
query42	0.04	0.02	0.02
query43	0.03	0.03	0.03
Total cold run time: 90.38 s
Total hot run time: 14.6 s

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review complete at exact head 0e66fd9522552abd9efa2bb685db6970859b19d1 against base 2573820600eb178150a35710a94fd58b478df96d after three bounded convergence rounds. Requesting changes for three P1 findings and one P2 finding attached inline.

Critical checkpoint conclusions

  • Goal and proof: The PR exposes ik_smart and ik_max_word to custom analyzers and covers the ordinary factory, reset, direct-offset, TOKENIZE, MATCH, CREATE, and ALTER paths. The happy path is coherent, but lazy error propagation, semantic identity, transforming-filter offsets, and unconditional resource costs keep the feature from being safely complete.
  • Scope and focus: The production change is generally focused on factory registration, tokenizer lifecycle/offsets, policy validation, and analyzer identity. All 22 authoritative changed files and their relevant callers/consumers were reviewed. No additional user focus was supplied, so the full PR remained in scope.
  • Concurrency: Factory publication and dictionary initialization use the existing process-wide call_once mechanisms; FE policy-map access remains under the existing reentrant lock discipline. No new thread, race, heavy-under-lock operation, inconsistent lock order, or deadlock issue was found.
  • Lifecycle/static initialization: Raw and shared readers, eager and reusable streams, reset-before-consume, EOF behavior, and source-map lifetime were traced. Reset and ownership are sound on supported production paths. The dictionary singleton itself is stable, but its new lazy creation point exposes the uncaught error boundary reported inline; no cross-TU static-order hazard was found.
  • Configuration: No new Doris runtime configuration key is added. Both modes use the established IK dictionary path and per-stream mode. No dynamic-configuration propagation gap was found.
  • Compatibility: No wire or storage-format field changes. Direct/case-variant factories align across FE and BE, and supported BE-before-FE rolling order avoids an old-BE factory gap. Replayed pre-upgrade tokenizer-name collisions are nevertheless misused by the new synthetic legacy identity, as reported inline.
  • Parallel paths: CREATE and ALTER share the faulty identity. TOKENIZE, row-fallback MATCH, and analyzed SEARCH all reach lazy tokenizer creation after their effective CLucene conversion boundary. Scalar/ARRAY writer and VARIANT metadata paths were separately traced; legal FE metadata does not route a custom analyzer into ARRAY ingestion, so that unsupported path is intentionally excluded from the finding.
  • Special conditions: The conditional reset is safe in the traced caller sequences. The legacy-identity guard omits behavior-affecting state, and term-text-only source-map forwarding is not compositional through a supported transforming filter; both are concrete inline findings.
  • Test coverage: Changed tests cover both modes, default legacy/custom duplicate detection in CREATE and ALTER, raw/shared reset contracts, synthetic IndexWriter ARRAY consumption, refill/direct full-width offsets, and deterministic TOKENIZE/MATCH results. Missing cases correspond to the four findings: first-use dictionary failure, legacy lower_case=false, replay-plus-duplicate identity, transforming-filter source offsets, and resource behavior. The residual dictionary test-order concern is already covered by an existing thread and was not reposted.
  • Test results: The regression uses ordered/deterministic output, pre-test drops, hardcoded table names, and expected-error form. Per the review contract, I ran no build or test, so these conclusions are static. Author-reported ASAN builds, combined BE tests, FE tests, and regression execution were treated as author evidence, not independent verification.
  • Observability: Existing dictionary logging is sufficient once failures are converted into Doris errors; no new metric is warranted. Letting a raw CLuceneError escape is an error-contract defect, not an observability substitute.
  • Persistence and transactions: Policy image/replay/name-map rebuilding was traced. No EditLog payload, transaction state machine, failover, or metadata-format change is introduced; replayed-name state is relevant only to the identity finding.
  • Data writes and crash behavior: Analyzer output affects inverted-index term generation, but no rowset/version/MoW, atomicity, partial-write, or crash-recovery defect was found. Direct offset/reset writer paths are sound; the supported transforming-filter chain still publishes incorrect source offsets.
  • FE-BE variables: No new Thrift or session variable is added. Existing string-valued policy properties carry the tokenizer/filter names; ordinary resolution agrees, with the synthetic-identity exception reported inline.
  • Performance and memory: The new source-map detector and enlarged eager token records affect every legacy/custom IK stream even when Pinyin is absent. This definite redundant scan and retained-memory growth is the P2 finding; no separate RTTI or memory-accounting finding was substantiated.
  • Other issues: Existing rendered threads and raw comments were treated as hard duplicate fences. Every candidate was ledgered and adjudicated. The final round narrowed supporting evidence but did not add or remove a finding; the stable four-finding set is complete within the three-round bound. Security review was neither requested nor implicated.

Comment thread be/src/storage/index/inverted/tokenizer/ik/ik_tokenizer_factory.h
Comment thread be/src/storage/index/inverted/token_filter/token_filter.h Outdated
Comment thread be/src/storage/index/inverted/analyzer/ik/IKTokenizer.cpp Outdated
airborne12 added a commit to airborne12/apache-doris that referenced this pull request Sep 13, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#67918

Problem Summary:

Lazy IK dictionary failures could escape the custom analyzer exception boundary, legacy IK identities could collide with behaviorally different or shadowed custom tokenizers, and pinyin offsets lost source-byte provenance after word delimiter processing. Source offset maps were also built even when no downstream filter consumed them.

Translate analyzer construction errors, keep legacy identity matching limited to equivalent built-in IK behavior, and make source-byte provenance opt-in and compositional through token filters. Preserve and rebase provenance for generated word delimiter parts and concatenations.

### Release note

None

### Check List (For Author)

- Test
    - [x] Regression test
    - [x] Unit Test

- Behavior changed:
    - [x] Yes. IK custom analyzers now report Doris analyzer errors, keep distinct identities for non-equivalent legacy settings, and preserve exact source offsets through delimiter and pinyin filters without unconditional mapping work.

- Does this need documentation?
    - [x] No.
@airborne12

Copy link
Copy Markdown
Member Author

run buildall

@airborne12

Copy link
Copy Markdown
Member Author

run buildall

@airborne12

Copy link
Copy Markdown
Member Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review result: no new non-duplicate findings on exact head 4ce410ca359c5e3e8842d5759dfe655881f9f503 (base 69b803b32a5ec914a4f4bfdaf45f6347c48435a0).

I reviewed the complete 95-file authoritative diff and converged after two independent review rounds. Plausible residuals were either already covered by the existing inline threads or disproved by the enclosing code (notably, VMatchPredicate construction is already inside VExpr::create_expr()'s Exception-to-Status boundary). I am not reposting those issues. Existing inline discussions remain the actionable review record; this summary does not clear or supersede them.

Checkpoint conclusions:

  • Goal, correctness, and tests: the changes consistently extend custom IK analysis, analyzer identity/policy binding, provenance-aware offsets, reader selection, and exception conversion across the reviewed paths. The added FE/BE unit and regression coverage exercises DDL, replay/collision cases, analyzer equivalence, malformed UTF-8, offset mapping, writer/reader failures, and query selection. No additional correctness defect survived duplicate and reachability checks.
  • Scope and focus: the broad FE/BE/test scope is cohesive around analyzer configuration and execution. No additional user-provided focus was supplied, and no extra issue was found for that focus.
  • Concurrency: FE/BE policy registries, analyzer-provider/factory reuse, and selected-reader state were checked against their lock/ownership patterns. I found no new race, lock-ordering, or unsafe shared-state issue.
  • Lifecycle and persistence: journal/image replay, exact and normalized name maps, drop/re-registration, analyzer stream reset/reuse, cached providers, and high-water cleanup were traced. Remaining legacy binding/migration concerns are already represented by existing threads.
  • Configuration and compatibility: no new server configuration item is introduced. Existing dictionary/analyzer properties, canonical built-ins, exact-name precedence, legacy aliases, serialized metadata, and mixed FE/BE behavior were reviewed; no new non-duplicate compatibility finding emerged.
  • Parallel paths: classic and SNII readers/writers, scalar and ARRAY writes, MATCH/slow fallback, direct SEARCH, scoring, typed reader selection, and phrase-capability gating were all checked, including lazy analyzer construction/tokenization failures.
  • Test results and observability: expected outputs and negative cases were inspected statically. Error conversion and existing logging are adequate for the changed failure paths; I found no distinct metrics/logging gap requiring a review comment.
  • Data safety, atomicity, and performance: this PR does not introduce a transaction or physical storage-format change. Policy-map updates, offset/provenance caps, malformed-input handling, reset/reuse, and memory high-water behavior were reviewed; no new atomicity, CPU, or memory issue was substantiated beyond existing threads.

Validation was static only, as required by the review environment. I did not build Doris or run tests.

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 27867 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 4ce410ca359c5e3e8842d5759dfe655881f9f503, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17769	3996	3995	3995
q2	2187	380	314	314
q3	10081	1398	802	802
q4	4680	474	349	349
q5	7493	826	553	553
q6	184	177	145	145
q7	750	788	599	599
q8	9310	1572	1537	1537
q9	5476	4220	4203	4203
q10	6839	1338	998	998
q11	437	283	252	252
q12	644	420	294	294
q13	18052	2627	1985	1985
q14	260	267	238	238
q15	q16	738	720	663	663
q17	1803	1130	943	943
q18	6511	5645	5578	5578
q19	1254	1219	1073	1073
q20	481	394	267	267
q21	5596	2937	2777	2777
q22	442	348	302	302
Total cold run time: 100987 ms
Total hot run time: 27867 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4304	4227	4190	4190
q2	719	572	557	557
q3	4465	4864	4330	4330
q4	2226	2327	1457	1457
q5	4239	4268	4137	4137
q6	233	180	135	135
q7	1761	1603	1456	1456
q8	2633	2281	2171	2171
q9	7557	7388	7508	7388
q10	3747	3628	3192	3192
q11	579	440	398	398
q12	714	718	536	536
q13	2437	2838	2183	2183
q14	282	294	272	272
q15	q16	708	733	628	628
q17	7968	7350	7112	7112
q18	11982	11085	11882	11085
q19	1187	1117	1086	1086
q20	2241	2231	1950	1950
q21	5606	4575	4418	4418
q22	527	469	400	400
Total cold run time: 66115 ms
Total hot run time: 59081 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152654 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 4ce410ca359c5e3e8842d5759dfe655881f9f503, data reload: false

query5	4328	629	468	468
query6	441	220	203	203
query7	4812	552	293	293
query8	329	180	180	180
query9	8834	3965	4015	3965
query10	454	319	255	255
query11	5901	3551	3223	3223
query12	146	92	87	87
query13	1306	651	439	439
query14	6536	4552	4241	4241
query14_1	3971	3973	3942	3942
query15	202	211	186	186
query16	990	468	433	433
query17	906	697	572	572
query18	2445	479	337	337
query19	214	186	147	147
query20	84	82	81	81
query21	227	137	116	116
query22	13035	13088	12811	12811
query23	13905	12919	12385	12385
query23_1	12438	12478	12524	12478
query24	7367	1124	664	664
query24_1	706	685	743	685
query25	564	447	381	381
query26	1124	317	170	170
query27	2670	554	318	318
query28	4508	1990	1966	1966
query29	1603	740	537	537
query30	297	239	186	186
query31	887	757	630	630
query32	152	97	97	97
query33	526	301	246	246
query34	1190	1146	622	622
query35	731	750	636	636
query36	787	793	734	734
query37	145	109	93	93
query38	1845	1768	1690	1690
query39	683	708	663	663
query39_1	665	644	682	644
query40	224	132	115	115
query41	109	65	65	65
query42	92	92	92	92
query43	327	339	297	297
query44	1379	718	727	718
query45	178	180	165	165
query46	1098	1220	764	764
query47	1481	1472	1417	1417
query48	401	427	304	304
query49	589	408	289	289
query50	1001	366	267	267
query51	10553	10593	10336	10336
query52	89	88	80	80
query53	241	263	179	179
query54	259	203	197	197
query55	77	73	68	68
query56	218	220	201	201
query57	1446	1457	1356	1356
query58	286	263	253	253
query59	1987	2080	1909	1909
query60	274	240	227	227
query61	150	153	139	139
query62	415	331	272	272
query63	218	173	178	173
query64	2630	1000	875	875
query65	3496	3425	3408	3408
query66	1768	415	294	294
query67	20144	20132	19980	19980
query68	3353	1552	988	988
query69	411	294	255	255
query70	888	814	817	814
query71	291	239	210	210
query72	2596	2512	2129	2129
query73	840	762	420	420
query74	4633	4476	4286	4286
query75	2282	2278	1915	1915
query76	2331	1129	773	773
query77	371	402	309	309
query78	8960	9096	8424	8424
query79	1375	1210	735	735
query80	593	464	378	378
query81	540	321	284	284
query82	624	164	129	129
query83	306	226	198	198
query84	317	149	118	118
query85	827	462	388	388
query86	321	242	235	235
query87	1989	1965	1847	1847
query88	3631	2723	2715	2715
query89	370	290	248	248
query90	1900	175	179	175
query91	170	157	129	129
query92	109	86	89	86
query93	1592	1412	853	853
query94	538	339	301	301
query95	643	455	338	338
query96	1028	794	357	357
query97	2430	2440	2332	2332
query98	165	156	151	151
query99	715	721	621	621
Total cold run time: 235895 ms
Total hot run time: 152654 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 23.98 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 4ce410ca359c5e3e8842d5759dfe655881f9f503, data reload: false

query1	0.01	0.01	0.00
query2	0.10	0.05	0.04
query3	0.26	0.14	0.13
query4	1.61	0.15	0.14
query5	0.24	0.22	0.22
query6	1.16	0.93	0.95
query7	0.04	0.01	0.01
query8	0.05	0.03	0.03
query9	0.39	0.34	0.36
query10	0.59	0.56	0.57
query11	0.20	0.15	0.14
query12	0.18	0.14	0.14
query13	0.45	0.46	0.48
query14	0.96	0.97	0.94
query15	0.62	0.57	0.58
query16	0.30	0.32	0.34
query17	1.08	1.08	1.08
query18	0.21	0.19	0.19
query19	2.04	1.95	1.87
query20	0.02	0.01	0.01
query21	15.47	0.22	0.14
query22	4.84	0.06	0.05
query23	16.12	0.30	0.13
query24	3.05	0.42	0.31
query25	0.13	0.04	0.04
query26	0.74	0.21	0.16
query27	0.05	0.04	0.04
query28	3.51	0.84	0.36
query29	12.51	4.11	3.18
query30	0.28	0.15	0.15
query31	2.76	0.56	0.32
query32	3.22	0.60	0.48
query33	3.15	3.15	3.21
query34	15.64	4.10	3.33
query35	3.26	3.23	3.24
query36	0.57	0.43	0.44
query37	0.09	0.06	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.18	0.15	0.15
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.34 s
Total hot run time: 23.98 s

…zed reader

Moving the support_phrase check into select_best_reader() made it run for
every selected reader and for every caller. That broke two things the old
preflight never touched:

- an untokenized index (USING INVERTED without a parser) never declares
  support_phrase and answers MATCH_PHRASE by matching the whole value as one
  term; the check rejected it (inverted_index_p0.test_index_complex_match,
  inverted_index_p0.test_omit_norms);
- direct SEARCH resolves its reader through select_best_reader() and has
  never enforced support_phrase; its regression suites run phrase clauses on
  parser indexes without it (search.test_search_function,
  search.test_search_dsl_syntax, search.test_search_multi_analyzer_lucene).

The check now lives in read_from_index(), applies only when the selected
reader is a FULLTEXT reader, and still checks the reader the analyzer
selected rather than the first full-text candidate. SEARCH keeps its
previous behaviour.

Tests: PhraseSupportIsCheckedOnTheSelectedReader now drives
read_from_index() in both index orders; PhraseQueriesStillRunOnAnUntokenizedIndex
covers the untokenized case for MATCH_PHRASE, MATCH_PHRASE_PREFIX and
MATCH_PHRASE_EDGE.
@airborne12

Copy link
Copy Markdown
Member Author

run buildall

@airborne12

Copy link
Copy Markdown
Member Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes for one backward-compatibility regression in explicit IK index selection.

Critical checkpoints:

  • Goal and correctness: the custom IK analyzer, exact policy binding, and configuration-aware reader selection are broadly coherent, but the FE now rejects an existing explicit query/index pairing before those mechanics can run.
  • Lifecycle and concurrency: exact/normalized policy registration, locking, create/drop, journal replay, image rebuild, and dependency checks were traced without another unresolved issue.
  • FE/BE compatibility and parallel paths: MATCH, direct/variant SEARCH, scoring, CLucene/SNII writers and readers, selected-reader phrase handling, and exception conversion were reviewed. Once FE selects an index, parser mode/lowercase/filter serialization agrees with the BE reader key; the accepted issue is the preceding FE compatibility gate.
  • Memory, offsets, and performance: provenance through changed tokenizers/filters, clipping, malformed input, reset/reuse, and high-water cleanup were reviewed with no new non-duplicate finding.
  • Tests: the added unit and regression coverage is extensive, but it locks in rejection of legacy parser=ik and lacks the single-existing-index upgrade case described inline. Per the review instructions, this was static analysis only; no builds or tests were run, so author/CI results were not independently reproduced.
  • Scope and focus: all 95 authoritative changed paths were swept, existing inline threads were treated as duplicate fences, and the user supplied no additional focus beyond the full review.

Comment thread fe/fe-core/src/main/java/org/apache/doris/analysis/InvertedIndexUtil.java Outdated
@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 27566 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 4a30b86113b5f2bba5888e49b43654e69e501e91, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17697	3806	3793	3793
q2	2150	346	313	313
q3	10083	1357	816	816
q4	4687	488	348	348
q5	7490	822	545	545
q6	182	175	144	144
q7	727	785	602	602
q8	9298	1350	1532	1350
q9	5417	4167	4144	4144
q10	6816	1328	1025	1025
q11	434	270	241	241
q12	630	426	289	289
q13	18037	2610	1998	1998
q14	261	254	232	232
q15	q16	739	711	667	667
q17	1812	1098	933	933
q18	6564	5596	5592	5592
q19	1308	1236	1073	1073
q20	494	376	263	263
q21	5812	3254	2903	2903
q22	438	361	295	295
Total cold run time: 101076 ms
Total hot run time: 27566 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4465	4402	4421	4402
q2	721	558	526	526
q3	4751	5320	4621	4621
q4	2238	2606	1466	1466
q5	4566	4448	4485	4448
q6	228	173	130	130
q7	1827	1726	1539	1539
q8	2330	2009	1995	1995
q9	7412	7080	6846	6846
q10	3594	3554	3078	3078
q11	528	379	340	340
q12	716	696	507	507
q13	2260	2601	1988	1988
q14	256	284	258	258
q15	q16	655	682	613	613
q17	7266	6786	6648	6648
q18	11835	11080	11632	11080
q19	1054	1010	1042	1010
q20	2194	2178	1922	1922
q21	5065	4065	4319	4065
q22	527	470	419	419
Total cold run time: 64488 ms
Total hot run time: 57901 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152366 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 4a30b86113b5f2bba5888e49b43654e69e501e91, data reload: false

query5	4306	607	476	476
query6	431	216	207	207
query7	4887	580	297	297
query8	330	177	173	173
query9	8844	4051	4043	4043
query10	439	313	253	253
query11	5844	3566	3224	3224
query12	152	92	86	86
query13	1277	635	450	450
query14	6578	4599	4306	4306
query14_1	3993	4072	3999	3999
query15	201	196	181	181
query16	1023	452	457	452
query17	915	688	541	541
query18	2427	482	330	330
query19	199	186	172	172
query20	83	84	83	83
query21	223	138	118	118
query22	13019	12911	12899	12899
query23	13850	13005	12636	12636
query23_1	12551	12509	12555	12509
query24	7273	1184	671	671
query24_1	736	720	697	697
query25	563	428	378	378
query26	1267	321	173	173
query27	2678	599	323	323
query28	4601	2082	2011	2011
query29	1546	726	509	509
query30	302	218	184	184
query31	885	752	633	633
query32	139	94	85	85
query33	506	298	241	241
query34	1209	1127	635	635
query35	705	734	627	627
query36	797	774	711	711
query37	146	101	95	95
query38	1812	1752	1704	1704
query39	696	700	647	647
query39_1	665	651	657	651
query40	225	122	96	96
query41	65	64	64	64
query42	95	93	91	91
query43	350	345	300	300
query44	1351	724	725	724
query45	183	174	163	163
query46	1059	1161	719	719
query47	1518	1473	1440	1440
query48	413	388	278	278
query49	602	423	300	300
query50	987	344	254	254
query51	10279	10452	10265	10265
query52	89	88	76	76
query53	248	264	186	186
query54	258	214	192	192
query55	84	75	70	70
query56	221	209	212	209
query57	1486	1403	1331	1331
query58	288	259	268	259
query59	2017	2067	1858	1858
query60	304	239	220	220
query61	149	147	149	147
query62	395	319	270	270
query63	215	176	177	176
query64	2804	1001	810	810
query65	3483	3405	3459	3405
query66	1824	409	312	312
query67	20156	19915	19868	19868
query68	3300	1456	882	882
query69	393	305	258	258
query70	897	780	867	780
query71	298	235	213	213
query72	2641	2500	1848	1848
query73	884	819	431	431
query74	4586	4561	4277	4277
query75	2296	2361	1969	1969
query76	2322	1121	750	750
query77	358	398	303	303
query78	9059	8962	8382	8382
query79	1364	1162	735	735
query80	570	450	364	364
query81	524	319	277	277
query82	607	170	129	129
query83	308	244	201	201
query84	317	140	110	110
query85	840	466	373	373
query86	321	242	226	226
query87	2000	1984	1856	1856
query88	3588	2732	2683	2683
query89	350	285	245	245
query90	1984	178	184	178
query91	166	151	127	127
query92	106	90	87	87
query93	1511	1376	828	828
query94	511	315	257	257
query95	668	389	435	389
query96	1086	750	358	358
query97	2431	2452	2303	2303
query98	186	149	140	140
query99	728	735	618	618
Total cold run time: 236183 ms
Total hot run time: 152366 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 23.68 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 4a30b86113b5f2bba5888e49b43654e69e501e91, data reload: false

query1	0.01	0.01	0.01
query2	0.09	0.04	0.04
query3	0.27	0.14	0.13
query4	1.61	0.14	0.14
query5	0.25	0.22	0.22
query6	1.16	0.92	0.91
query7	0.04	0.01	0.01
query8	0.05	0.04	0.03
query9	0.38	0.35	0.35
query10	0.55	0.55	0.54
query11	0.20	0.15	0.14
query12	0.17	0.15	0.15
query13	0.47	0.47	0.48
query14	0.94	0.95	0.94
query15	0.59	0.60	0.57
query16	0.31	0.31	0.30
query17	1.08	1.04	1.04
query18	0.22	0.20	0.20
query19	2.06	1.94	1.87
query20	0.02	0.01	0.02
query21	15.47	0.20	0.12
query22	4.83	0.05	0.06
query23	16.14	0.31	0.12
query24	2.94	0.43	0.30
query25	0.10	0.05	0.04
query26	0.74	0.21	0.15
query27	0.04	0.04	0.03
query28	3.53	0.78	0.33
query29	12.47	3.95	3.18
query30	0.27	0.16	0.15
query31	2.77	0.54	0.30
query32	3.22	0.59	0.48
query33	3.07	3.20	3.13
query34	15.82	3.92	3.29
query35	3.20	3.17	3.23
query36	0.54	0.43	0.42
query37	0.09	0.07	0.06
query38	0.05	0.04	0.04
query39	0.04	0.03	0.04
query40	0.17	0.15	0.14
query41	0.08	0.03	0.03
query42	0.04	0.03	0.02
query43	0.04	0.03	0.04
Total cold run time: 96.13 s
Total hot run time: 23.68 s

…cy IK index

Explicit built-in IK selects an index by its effective configuration since
4501552, so a pre-upgrade table whose only IK index is parser=ik
(ik_smart) no longer matched MATCH ... USING ANALYZER ik and the query
failed with "No inverted index found for analyzer 'ik'".

OlapTable.filterIndexesByAnalyzer() now falls back to the single index that
carries the requested name when no index matches the configuration. The
name check is InvertedIndexUtil.isAnalyzerNameMatched(), split out of
isAnalyzerMatched(), which is unchanged. The predicate serializes that
index's own parser_mode and lower_case, so BE binds its reader and
tokenizes the query the same way. Two differently configured legacy
indexes remain ambiguous.

Tests: InvertedIndexPropertiesTest covers the single legacy index, legacy
plus default, and the ambiguous pair; test_analyzer_identity_semantics adds
a table whose only index is parser=ik and checks smart-mode results.
@airborne12

Copy link
Copy Markdown
Member Author

run buildall

@airborne12

Copy link
Copy Markdown
Member Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review result: request changes for one P1 FE/BE analyzer-identity mismatch.

A replayed legacy TOKEN_FILTER named LOWERCASE can make FE assign the built-in lowercase normalizer the identity of an ASCII-folding policy, even though BE executes the built-in lowercase pipeline. CREATE and ALTER can consequently reject two indexes whose runtime analyzers differ; the inline comment gives the concrete chain.

Critical checkpoint conclusions:

  • Goal and proof: the PR broadly adds custom IK tokenizers and aligns replay binding, analyzer selection, semantic duplicate fences, failure conversion, and source-byte provenance. The remaining false-equivalence case prevents the duplicate-index goal from being complete. Existing tests are broad but do not cover a case-distinct legacy TOKEN_FILTER shadowing the built-in normalizer identity.
  • Scope and clarity: all 96 authoritative changed paths were reconciled. The production and test changes are cohesive around analyzer policies, selection, execution, and provenance; no unrelated production change remained.
  • Concurrency: FE policy maps retain read/write-lock protection, BE policy maps retain shared-mutex protection, and mutable analyzer/provenance state is instance-local. No lock-order, race, deadlock, or heavy-operation-under-lock defect was substantiated.
  • Lifecycle, persistence, and compatibility: create, image/journal replay, policy reporting, drop/fallback restoration, provider binding, reader selection, reset/reuse, and the supported BE-first compatibility path were traced. MAIN-01 is the remaining replay-state mismatch; no other lifecycle, failover, or rolling-upgrade issue survived review.
  • Configuration and protocol: no new dynamic server configuration or Thrift field is introduced. Analyzer/mode/lowercase/filter properties reach the relevant FE and BE paths consistently outside the inline identity bug.
  • Parallel paths and error handling: classic and ARRAY writers, MATCH, direct SEARCH, Variant, scoring, CLucene/SNII readers, compaction, and phrase checks were compared. New IK failures and changed ICU/NGram failures reach Doris/CLucene-to-Status boundaries. A scalar Pinyin exception gap considered during review predates this PR and was not submitted as a PR finding.
  • Data writes and atomicity: analysis failures abort document construction instead of publishing partial index state. No transaction, version, MoW, Cloud, crash-consistency, or nullable-column change is introduced here.
  • Memory and performance: provenance maps and scratch buffers are reset/reused and oversized scratch is released. No distinct leak, unsafe lifetime, allocator issue, or material hot-path regression survived review.
  • Tests and expected results: FE/BE unit and regression changes cover current binding, selection, malformed input, reset/reuse, and many semantic aliases. Missing blocking coverage is CREATE and ALTER with replayed LOWERCASE(type=asciifolding), built-in LowerCase, and a named ASCII-folding normalizer. Checked-in expected outputs were inspected statically.
  • Observability and security: current analyzer statuses and policy logs are adequate for these paths; the change introduces no authentication, authorization, tenancy, or new outbound trust boundary.
  • User focus: no additional focus was supplied.

Validation was static only against the authoritative merge-base-to-head diff and related call chains. I did not run builds or tests, and author/CI results were not independently revalidated.

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 28457 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 2e22e296ea6a6f643aaa25004d87ccc9dfc75889, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17862	4075	4134	4075
q2	2192	353	304	304
q3	10083	1468	847	847
q4	4692	495	349	349
q5	7514	883	585	585
q6	193	185	147	147
q7	765	806	620	620
q8	9326	1535	1510	1510
q9	5435	4244	4194	4194
q10	6842	1358	1026	1026
q11	442	285	251	251
q12	644	428	310	310
q13	18056	2629	2018	2018
q14	275	258	243	243
q15	q16	743	720	667	667
q17	1790	1158	1032	1032
q18	6609	5606	5564	5564
q19	1353	1198	994	994
q20	508	406	269	269
q21	6113	3470	3133	3133
q22	473	379	319	319
Total cold run time: 101910 ms
Total hot run time: 28457 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5202	4793	4759	4759
q2	774	599	541	541
q3	4993	5137	4634	4634
q4	2289	2417	1543	1543
q5	4634	4617	4749	4617
q6	232	177	134	134
q7	1865	1742	1527	1527
q8	2440	2287	2243	2243
q9	7347	7299	7269	7269
q10	3663	3599	3099	3099
q11	530	372	349	349
q12	721	720	508	508
q13	2311	2611	2009	2009
q14	261	276	251	251
q15	q16	672	702	621	621
q17	7417	6866	6719	6719
q18	11860	11080	11689	11080
q19	1119	1033	1006	1006
q20	2212	2207	1917	1917
q21	5230	4301	4481	4301
q22	553	483	424	424
Total cold run time: 66325 ms
Total hot run time: 59551 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 153084 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 2e22e296ea6a6f643aaa25004d87ccc9dfc75889, data reload: false

query5	4307	628	465	465
query6	417	223	193	193
query7	4870	538	295	295
query8	317	181	162	162
query9	8806	3999	3962	3962
query10	461	305	255	255
query11	5824	3566	3222	3222
query12	141	88	89	88
query13	1243	557	414	414
query14	6525	4562	4272	4272
query14_1	4040	4003	3964	3964
query15	200	206	179	179
query16	1007	476	469	469
query17	916	691	552	552
query18	2436	457	329	329
query19	208	205	152	152
query20	83	81	80	80
query21	224	134	118	118
query22	13004	13034	12846	12846
query23	14291	13064	12639	12639
query23_1	12486	12531	12690	12531
query24	7441	1111	700	700
query24_1	664	733	700	700
query25	532	408	343	343
query26	1262	310	164	164
query27	2736	553	325	325
query28	4542	1987	1980	1980
query29	1616	707	510	510
query30	300	224	186	186
query31	877	753	619	619
query32	160	96	97	96
query33	511	315	253	253
query34	1186	1094	639	639
query35	717	760	641	641
query36	806	793	729	729
query37	143	104	92	92
query38	1845	1768	1685	1685
query39	682	700	669	669
query39_1	651	655	630	630
query40	224	122	101	101
query41	67	65	63	63
query42	95	96	91	91
query43	335	339	305	305
query44	1392	743	734	734
query45	190	174	168	168
query46	1058	1180	740	740
query47	1513	1506	1398	1398
query48	429	427	303	303
query49	587	404	289	289
query50	951	354	269	269
query51	10330	10581	10408	10408
query52	88	88	75	75
query53	242	257	191	191
query54	266	221	191	191
query55	84	73	68	68
query56	257	228	214	214
query57	1455	1351	1312	1312
query58	293	265	247	247
query59	1990	2071	1858	1858
query60	275	244	214	214
query61	146	153	149	149
query62	413	320	270	270
query63	213	175	175	175
query64	2807	1018	838	838
query65	3523	3428	3440	3428
query66	1776	420	309	309
query67	20063	20076	19951	19951
query68	3171	1498	969	969
query69	398	306	255	255
query70	907	816	844	816
query71	289	234	212	212
query72	2803	2670	2242	2242
query73	852	773	428	428
query74	4632	4476	4294	4294
query75	2272	2277	1924	1924
query76	2302	1122	766	766
query77	374	395	304	304
query78	8994	9003	8420	8420
query79	1169	1237	750	750
query80	527	454	370	370
query81	525	324	289	289
query82	283	171	124	124
query83	219	225	201	201
query84	299	144	119	119
query85	860	487	388	388
query86	344	245	225	225
query87	2009	1983	1839	1839
query88	3619	2743	2717	2717
query89	316	286	248	248
query90	2176	182	183	182
query91	168	160	144	144
query92	103	88	90	88
query93	1402	1416	884	884
query94	538	358	308	308
query95	712	383	420	383
query96	1043	773	331	331
query97	2429	2427	2317	2317
query98	156	149	140	140
query99	726	742	617	617
Total cold run time: 235774 ms
Total hot run time: 153084 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.08 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 2e22e296ea6a6f643aaa25004d87ccc9dfc75889, data reload: false

query1	0.01	0.01	0.00
query2	0.10	0.05	0.05
query3	0.27	0.14	0.14
query4	1.61	0.14	0.13
query5	0.24	0.24	0.23
query6	1.17	0.97	0.96
query7	0.04	0.01	0.01
query8	0.07	0.04	0.04
query9	0.41	0.34	0.34
query10	0.55	0.57	0.57
query11	0.20	0.15	0.13
query12	0.18	0.15	0.15
query13	0.46	0.48	0.46
query14	0.95	0.95	0.97
query15	0.62	0.58	0.60
query16	0.32	0.33	0.33
query17	1.10	1.10	1.10
query18	0.23	0.22	0.21
query19	2.04	1.93	1.96
query20	0.02	0.02	0.01
query21	15.49	0.21	0.14
query22	4.84	0.05	0.05
query23	16.13	0.31	0.12
query24	3.02	0.41	0.33
query25	0.11	0.08	0.04
query26	0.73	0.20	0.14
query27	0.04	0.03	0.04
query28	3.54	0.82	0.35
query29	12.48	4.05	3.26
query30	0.29	0.15	0.14
query31	2.76	0.57	0.31
query32	3.22	0.59	0.48
query33	3.15	3.20	3.09
query34	15.56	3.95	3.28
query35	3.22	3.23	3.23
query36	0.58	0.43	0.41
query37	0.09	0.07	0.06
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.17	0.15	0.14
query41	0.08	0.03	0.02
query42	0.04	0.03	0.03
query43	0.05	0.04	0.04
Total cold run time: 96.27 s
Total hot run time: 24.08 s

@airborne12

Copy link
Copy Markdown
Member Author

run external

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 91.29% (304/333) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.32% (34449/45135)
Line Coverage 61.27% (387193/631959)
Region Coverage 57.59% (325621/565451)
Branch Coverage 58.43% (148561/254260)

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 48.75% (429/880) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 91.29% (304/333) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.65% (34598/45135)
Line Coverage 61.72% (390064/631959)
Region Coverage 58.27% (329477/565451)
Branch Coverage 59.00% (150007/254260)

@airborne12

Copy link
Copy Markdown
Member Author

run external

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 48.75% (429/880) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 91.29% (304/333) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.30% (34438/45135)
Line Coverage 61.24% (387019/631959)
Region Coverage 57.57% (325513/565451)
Branch Coverage 58.40% (148497/254260)

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 48.75% (429/880) 🎉
Increment coverage report
Complete coverage report

@eldenmoon eldenmoon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants